package br.com.lm.anotacoes;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map; 
import java.util.Set;

/**
 * @author Robson Motta
 * Representa todas as anotacoes para uma classe em um determinado Pacote
 */
public class AnnotationElement {

    //Informacoes da classe que contem anotacoes
    private String classNameWithAnnotation;
    private String packageClassName;
	
    //HashMap( String nomeAnotacao, Set AnnotationData )
    private Map<String, Set<AnnotationData>> elements;

    /**
     * @return - HashMap( String nomeAnotacao, Set AnnotationData )
     */            
    public Map<String, Set<AnnotationData>> getAllAnnotationData() {
	return elements;
    }

    /**
     * @return - HashSet( String nomeAnotacao )  
     */
    public Set<String> getAllAnnotationName() {
	return elements == null ? null : elements.keySet();
    }

    /**
     * @return - String[] de todos os nomes de anotacoes 
     */	
    public String[] getArrayAnnotationName() {
	return elements == null ? null : (String[])elements.keySet().toArray();
    }

    /**	
     * @param annotationName - Nome da anotacao em (@interface)
     * @return - HashSet( AnnotationData )  
     */
    public Set<AnnotationData> getAnnotationByName(String annotationName){
	return elements == null ? null : elements.get(annotationName);
    }

    /** 
     * @param annotationType - Tipo da anotacao (Class, Field, Constructor e Method)
     * @return - HashMap( String nomeAnotacao, Set AnnotationData ) 
     */
    @SuppressWarnings("UnusedAssignment")
    public Map<String, Set<AnnotationData>> getAnnotationByType(AnnotationType annotationType){
	Map<String, Set<AnnotationData>> result = null;
        Set<AnnotationData> annoDatas = null; 
	if (elements != null) {
            Set<Map.Entry<String, Set<AnnotationData>>> set = elements.entrySet();
            for (Iterator<Map.Entry<String, Set<AnnotationData>>> iter = set.iterator(); iter.hasNext();) {
                //Anotacao
		Map.Entry<String, Set<AnnotationData>> me = iter.next();
                //Detalhes da anotacao
                annoDatas = null;
                for (AnnotationData annoData: me.getValue()) {
                    if (annoData.getAnnotationType().equals(annotationType)) {
                        if (annoDatas == null)
                            annoDatas = new HashSet<AnnotationData>();
                        annoDatas.add(annoData);
                    }
                }
                if (annoDatas != null) {
                    if (result == null)
                        result = new HashMap<String, Set<AnnotationData>>();
                    result.put(me.getKey(), annoDatas);
                }
             }
	}
	return result;
    }
		 
    /**
     * @param annotationName - Nome da anotacao em (@interface)
     * @param annotationType - Tipo da anotacao (Class, Field, Constructor e Method)
     * @return - HashSet( AnnotationData )
     */
    public Set<AnnotationData> getAnnotationByNameAndType(String annotationName, AnnotationType annotationType){
	Set<AnnotationData> result = null;
	if (elements != null) {
            Set<AnnotationData> annDatas = elements.get(annotationName);
            if (annDatas != null) {
                for (AnnotationData ann:annDatas) {
                    if (ann.getAnnotationType().equals(annotationType)) {
                        if (result == null)
                            result = new HashSet<AnnotationData>();
                        result.add(ann);
                    }
                }
            }
	}		
	return result;
    }
	
    /**
     * @param annotationName - Nome da anotacao em (@interface)
     * @param annotationMember - Identificacao do method da anotacao
     * @return - HashSet( AnnotationData )
     */
    public Set<AnnotationData> getAnnotationByNameAndElemtKey(String annotationName, String annotationMember){
        Set<AnnotationData> result = null;
        if (elements != null) {
            Set<AnnotationData> annDatas = elements.get(annotationName);
            if (annDatas != null) {
                for (AnnotationData ann:annDatas) {
                    if (ann.getAnnotationMember().equals(annotationMember)) {
                        if (result == null)
                            result = new HashSet<AnnotationData>();
                        result.add(ann);
                    }
                }
            }
        }		
        return result;
    }	
	
    /**
     * @param annotationName - Nome da anotacao em (@interface)
     * @param annotationType - Tipo da anotacao (Class, Field, Constructor e Method)
     * @param annotationMember - Identificacao do method da anotacao  
     * @return - HashSet ( AnnotationData )
     */
    public Set<AnnotationData> getAnnotationByNameTypeElementKey(String annotationName, AnnotationType annotationType, String annotationMember){
	Set<AnnotationData> result = null;
	if (elements != null) {
            Set<AnnotationData> annDatas = elements.get(annotationName);
            if (annDatas != null) {
                for (AnnotationData ann:annDatas) {
                    if (ann.getAnnotationType().equals(annotationType) && ann.getAnnotationMember().equals(annotationMember)) {
                        if (result == null)
                            result = new HashSet<AnnotationData>();
			result.add(ann); 
                    }
		}
            }
	}		
	return result;
    }
	
    /**
     * @return - Nome da Classe que foi atribuida anotacoes 
     */
    public String getClassNameWithAnnotation() {
	return classNameWithAnnotation;
    }

    public void setClassNameWithAnnotation(String classNameWithAnnotation) {
	this.classNameWithAnnotation = classNameWithAnnotation;
    }

    /**
     * @return - O package da classe que foi atribuida anotacoes 
     */
    public String getPackageClassName() {
	return packageClassName;
    }

    public void setPackageClassName(String packageClassName) {
	this.packageClassName = packageClassName;
    }	

    public void setAllAnnotationData(Map<String, Set<AnnotationData>> elements) {
	this.elements = elements;
    }
}
